package cn.edu.tju.elm.service;

import cn.edu.tju.elm.model.Order;
import cn.edu.tju.elm.repository.OrderRepository;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;

/**
 * ClassName: OrderService
 * Package: cn.edu.tju.elm.service
 * Description:
 *
 * @Author Niu Wenhang
 * @Create 2025/9/17 22:20
 * @Version 1.0
 */
@Service
@Transactional
public class OrderService {
    private final OrderRepository orderRepository;

    public OrderService(OrderRepository orderRepository) {
        this.orderRepository = orderRepository;
    }

    public Order addOrder(Order order) {
        return orderRepository.save(order);
    }

    public Optional<Order> getOrderById(Long id) {
        return orderRepository.findOrderWithDetailsAndFoodById(id);
    }

    public List<Order> getOrdersByUserId(Long userId) {
        return orderRepository.findByCustomerIdAndDeletedFalse(userId);
    }

    public Order updateOrder(Order order) {
        return orderRepository.save(order);
    }

    public List<Order> getOrdersByBusinessId(Long businessId) {
        return orderRepository.findByBusinessIdAndDeletedFalse(businessId);
    }

    public List<Order> getOrdersByUserIdAndStatus(Long userId, Integer orderStatus) {
        return orderRepository.findByCustomerIdAndOrderStateAndDeletedFalse(userId, orderStatus);
    }

    public List<Order> getOrdersByUserIdAndDateRange(Long userId, String startDate, String endDate) {
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        LocalDate start = LocalDate.parse(startDate, formatter);
        LocalDate end = LocalDate.parse(endDate, formatter);
        return orderRepository.findByCustomerIdAndOrderDateBetweenAndDeletedFalse(userId, start, end);
    }

    public List<Order> getOrdersByUserIdAndTotalRange(Long userId, BigDecimal minTotal, BigDecimal maxTotal) {
        return orderRepository.findByCustomerIdAndOrderTotalBetweenAndDeletedFalse(userId, minTotal, maxTotal);
    }

    public List<Order> getRecentOrdersByUserId(Long userId, Integer limit) {
        return orderRepository.findByCustomerIdAndDeletedFalse(userId).stream()
                .sorted((o1, o2) -> o2.getCreateTime().compareTo(o1.getCreateTime()))
                .limit(limit)
                .collect(java.util.stream.Collectors.toList());
    }

    public Map<String, Object> getOrderStatisticsByUserId(Long userId) {
        List<Order> orders = orderRepository.findByCustomerIdAndDeletedFalse(userId);
        
        Map<String, Object> statistics = new HashMap<>();
        statistics.put("totalOrders", orders.size());
        
        if (!orders.isEmpty()) {
            BigDecimal totalAmount = orders.stream()
                    .map(Order::getOrderTotal)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            statistics.put("totalAmount", totalAmount);
            
            BigDecimal averageAmount = totalAmount.divide(new BigDecimal(orders.size()), 2, BigDecimal.ROUND_HALF_UP);
            statistics.put("averageAmount", averageAmount);
            
            // 按状态统计
            Map<Integer, Long> statusCount = new HashMap<>();
            for (Order order : orders) {
                statusCount.merge(order.getOrderState(), 1L, Long::sum);
            }
            statistics.put("statusCount", statusCount);
            
            // 最近订单
            Order recentOrder = orders.stream()
                    .max((o1, o2) -> o1.getCreateTime().compareTo(o2.getCreateTime()))
                    .orElse(null);
            statistics.put("recentOrder", recentOrder);
        } else {
            statistics.put("totalAmount", BigDecimal.ZERO);
            statistics.put("averageAmount", BigDecimal.ZERO);
            statistics.put("statusCount", new HashMap<>());
            statistics.put("recentOrder", null);
        }
        
        return statistics;
    }
}
